
package com.task.base;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.view.*;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.*;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.List;

public class ApplicationActivity extends ListActivity {

    private static final int ITEM_RUN = 0;

    private static final int ITEM_UNINSTALL = 1;

    private static final int ITEM_DETAIL = 2;

    private Context context = null;

    private TextView applications;

    private TextView space;

    private long totalLoad, totalDelta, totalWork, workDelta;

    private PackageManager mPm;

    private ActivityManager am;

    private HashMap<String, SoftReference<Drawable>> processItemMaps;

    // private String preMemory;

    // private String preCpu;

    private byte[] buf = new byte[512];

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.application);
        dialog = ProgressDialog.show(this, null, getString(R.string.loading));
        context = this;
        am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        mPm = getPackageManager();
        processItemMaps = new HashMap<String, SoftReference<Drawable>>();
        // preMemory = getString(R.string.memory);
        // preCpu = getString(R.string.cpu);
        initializeApplicationInfo();
        initList();
        registerForContextMenu(getListView());
    }

    @Override
    public void onDestroy() {
        ((ArrayAdapter<ProcessItem>) getListView().getAdapter()).clear();
        context = null;
        applications = null;
        space = null;
        super.onDestroy();
    }

    /**
     * 初始化应用程序信息
     */
    private void initializeApplicationInfo() {
        applications = (TextView) findViewById(R.id.applications);
        space = (TextView) findViewById(R.id.space);
    }

    private void initList() {

        // // 长按某一项相应监听器
        // MyOnItemLongClickListener longClickListener = new
        // MyOnItemLongClickListener();
        // this.getListView().setOnItemLongClickListener(longClickListener);

        // 这个初始化之前需要先初始化onClickButtonlistener
        ArrayAdapter<ProcessItem> adapter = new ArrayAdapter<ProcessItem>(this,
                R.layout.app_list_item) {

            @Override
            public View getView(int position, View convertView, android.view.ViewGroup parent) {
                View view;
                TextView txt_name, txt_size;
                ImageView img_type;
                ImageButton closeButton;

                if (convertView == null) {
                    view = LayoutInflater.from(context).inflate(R.layout.app_list_item, parent,
                            false);
                } else {
                    view = convertView;
                }

                if (position >= getCount()) {
                    return view;
                }

                ProcessItem itm = getItem(position);

                img_type = (ImageView) view.findViewById(R.id.itemImage);
                txt_name = (TextView) view.findViewById(R.id.name);
                txt_size = (TextView) view.findViewById(R.id.appSize);

                closeButton = (ImageButton) view.findViewById(R.id.buttonClose);

                String lb = itm.label;
                if (itm.sys) {
                    lb += " *";
                }
                txt_name.setText(lb);

                img_type.setImageDrawable(itm.icon);

                txt_size.setText(Util.getAppContainSize(itm.applicationInfo, context, mPm));
                closeButton.setTag(itm.packageName);
                closeButton.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        String packageName = (String) v.getTag();
                        Util.unintallApplication(packageName, context);
                    }
                });
                closeButton.setFocusable(false);// 由于按钮会和listView抢夺焦点所有需要设置一下
                view.setTag(itm);
                return view;
            }
        };

        getListView().setAdapter(adapter);
    }

    private PopupWindow menuPopup;

    private View menuLayout;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add("menu");// 必须添加一个，其实用不到

        if (null == menuPopup) {

            menuLayout = getLayoutInflater().inflate(R.layout.options_menu_application, null);

            menuPopup = new PopupWindow(menuLayout, LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT);

            menuPopup.setFocusable(true);// 必须，否则无法点击子view
            menuPopup.setOutsideTouchable(true);// 必须，否则点击其它区域无法关闭
            menuPopup.setBackgroundDrawable(new BitmapDrawable());// 同上
            menuPopup.setAnimationStyle(R.style.MenuAnimation);

            menuPopup.setTouchInterceptor(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getY() < 0) {
                        if (menuPopup.isShowing())
                            menuPopup.dismiss();
                    }
                    return false;
                }
            });

            menuLayout.setFocusableInTouchMode(true);// 必须，否则下面的事件不起作用

            menuLayout.setOnKeyListener(new OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if ((keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK)
                            && (menuPopup.isShowing())) {
                        menuPopup.dismiss();
                        return true;
                    }
                    return false;
                }
            });

            ((Button) menuLayout.findViewById(R.id.menu_settings))
                    .setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                            handler.sendEmptyMessage(MSG_MENU_DISMISS);
                            Intent intent = new Intent(ApplicationActivity.this,
                                    SettingActivity.class);
                            startActivity(intent);

                        }
                    });

            ((Button) menuLayout.findViewById(R.id.menu_statistics))
                    .setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                            handler.sendEmptyMessage(MSG_MENU_DISMISS);
                            Intent intent = new Intent(Intent.ACTION_MAIN);
                            intent.setComponent(new ComponentName("com.android.settings",
                                    "com.android.settings.UsageStats"));
                            startActivity(intent);
                        }
                    });

        }

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menuPopup.isShowing())
            menuPopup.dismiss();
        else
            menuPopup.showAtLocation(findViewById(R.id.layoutRoot), Gravity.BOTTOM, 0, 0);
        return false;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;

        ProcessItem item = (ProcessItem) info.targetView.getTag();

        if (item != null) {
            menu.setHeaderIcon(item.icon);
            menu.setHeaderTitle(item.label);
            menu.add(0, ITEM_RUN, 0, R.string.run_application);
            if (!item.sys) {
                menu.add(0, ITEM_UNINSTALL, 1, R.string.uninstall);
            }
            menu.add(0, ITEM_DETAIL, 2, R.string.detail);
        }
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        ProcessItem itm = (ProcessItem) menuInfo.targetView.getTag();
        String packageName = itm.packageName;

        switch (item.getItemId()) {
            case ITEM_RUN:
                Util.runApplication(packageName, mPm, context);
                break;
            case ITEM_UNINSTALL:
                Util.unintallApplication(packageName, context);
                break;
            case ITEM_DETAIL:
                Util.runApplicationDetails(packageName, context);
                break;
        }
        return super.onContextItemSelected(item);
    }

    private static final int MSG_INIT_OK = 5;

    private static final int MSG_MENU_DISMISS = 0;

    private HashMap<Integer, Long> processCpu = new HashMap<Integer, Long>();

    ProgressDialog dialog;

    /**
     * 更新list中数据。
     */
    private void updateListData() {

        List<ApplicationInfo> installedAppList = mPm
                .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);

        applications.setText(" " + installedAppList.size() + "");
        String[] storageInfo = Util.getStorageInfo(this);
        space.setText(storageInfo[0] + "/" + storageInfo[1]);

        updateCpuInfo();

        ArrayAdapter<ProcessItem> adapter = (ArrayAdapter<ProcessItem>) getListView().getAdapter();
        processCpu.clear();
        int pid = 0;
        for (int i = 0; i < adapter.getCount(); i++) {
            pid = adapter.getItem(i).pid;
            if (pid > 0) {
                processCpu.put(pid, adapter.getItem(i).cputime);
            }
        }

        adapter.setNotifyOnChange(false);
        adapter.clear();

        RunningAppProcessInfo currentProcess = null;
        ProcessItem currentItem = null;
        boolean isSys = false;
        Drawable icon = null;
        SoftReference<Drawable> reference;
        for (ApplicationInfo appInfo : installedAppList) {
            currentItem = new ProcessItem();
            icon = null;
            reference = processItemMaps.get(appInfo.packageName);

            if (reference != null) {
                icon = reference.get();
            }
            if (icon == null) {
                icon = appInfo.loadIcon(mPm);
                processItemMaps.put(appInfo.packageName, new SoftReference<Drawable>(icon));
            }
            currentItem.icon = icon;
            currentProcess = isRunningProcess(appInfo.packageName);
            // 判断是否系统程序

            isSys = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;

            currentItem.sys = isSys;

            if (currentProcess == null) {
                currentItem.mem = "0KB";// 说明当前不是进程
                currentItem.pid = 0;
            } else {
                // 如果是进程
                currentItem.pid = currentProcess.pid;
                if (processCpu.containsKey(currentItem.pid)) {
                    currentItem.lastcputime = processCpu.get(currentItem.pid);
                }

                Util.readProcessStat(context, buf, currentItem);
            }

            currentItem.label = appInfo.loadLabel(mPm).toString();
            currentItem.packageName = appInfo.packageName;
            currentItem.applicationInfo = appInfo;
            adapter.add(currentItem);

        }
        processCpu.clear();
        adapter.notifyDataSetChanged();
        dialog.dismiss();
    }

    /**
     * 判断当前的应用程序是否是正在运行的进程.
     * 
     * @param packageName
     * @return
     */
    private RunningAppProcessInfo isRunningProcess(String packageName) {
        List<RunningAppProcessInfo> raps = am.getRunningAppProcesses();
        for (RunningAppProcessInfo process : raps) {
            if (process.processName.equals(packageName)) {
                return process;
            }
        }
        return null;

    }

    Handler handler = new Handler() {

        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_INIT_OK:
                    updateListData();
                    // handler.postDelayed(task, 3000);
                    break;
                case MSG_MENU_DISMISS:
                    if (menuPopup != null && menuPopup.isShowing()) {
                        menuPopup.dismiss();
                    }
                    break;

            }
        };
    };

    @Override
    protected void onResume() {
        super.onResume();
        handler.sendEmptyMessageDelayed(MSG_INIT_OK, 100);
        if (menuPopup != null && menuPopup.isShowing())
            menuPopup.dismiss();

    }

    @Override
    protected void onPause() {
        // handler.removeCallbacks(task);
        handler.removeMessages(MSG_INIT_OK);

        super.onPause();
    }

    /**
     * 更新获取总体CPU使用时间。
     */
    private void updateCpuInfo() {
        long[] loads = Util.readCpuLoad();

        long newload = loads == null ? 0 : (loads[0] + loads[1]);

        if (totalLoad != 0) {
            totalDelta = newload - totalLoad;
        }

        totalLoad = newload;

        long newWork = loads == null ? 0 : loads[0];

        if (totalWork != 0) {
            workDelta = newWork - totalWork;
        }

        totalWork = newWork;
    }

    /**
     * 获取cpu使用率，单位是百分比。
     * 
     * @return
     */
    public long getCpuUsage() {
        long cpu = totalDelta == 0 ? 0 : (workDelta * 100 / totalDelta);

        if (cpu < 0) {
            cpu = 0;
        }
        if (cpu > 100) {
            cpu = 100;
        }
        return cpu;
    }
}
